LVS Load Balancing Cluster - Configurazione

Questo infobox e' la prosecuzione della parte introduttiva ad LVS e descrive i vari passaggi della configurazione di un piccolo cluster che ho realizzato costituito da bilanciatore e due nodi con funzionalita' di proxy http. Per maggiori dettagli sulle scelte effettuate (instradamento, algoritmo di bilanciamento, persistenza) si rimanda all'infobox introduttivo.  
Innanzitutto, non avendo avuto la possibilita' di ridondare il bilanciatore facendo due macchine in cluster ha tramite heartbeat si e' cercato di garantire quantomeno la ridondanza delle interfacc di rete, configurandole in bonding secondo la modalita' Active-Backup. Avendo gia' trattato l'argomento in un altro infobox si rimanda allo stesso per i dettagli della configurazione. Quindi eventuali riferimenti alla scheda di rete nell'infobox riguarderanno bond0 anziche' ethx.  

Per prima cosa e' necessario installare i seguenti pacchetti:  
  
apt-get install ldirectord  
apt-get install ipvsadm  
  
Ipvsadm consente di modificare la configurazione di LVS aggiungendo e rimuovendo servizi, modificando la modalita' di forwarding, paradigmi di bilanciamento, ecc. Ldirectord e' invece un demone che consente di monitorare i servizi erogati dai nodi fisici ed in base allo stato rilevato aggiungerli o rimuoverli dinamicamente al bilanciamento.  
Se ad esempio uno dei due proxy dovesse spegnersi o il relativo servizio crashare, ldirectord dovrebbe accorgersi del cambio di stato (ad esempio perche' impossibilitato a connettersi alla porta dove il servizio e' in ascolto) e togliere a caldo il nodo dal bilanciamento.  

Ldirectord e' personalizzabile tramite file di configurazione, nel mio caso /etc/ldirectord.conf:  
                   
# /etc/ldirectord.conf  
# --------------------        
# Ldirectord configuration file to configure various virtual services.  
#  

checktimeout=20  
checkinterval=10  
autoreload=yes  
logfile="/var/log/ldirectord.log"  
quiescent=no  

virtual=10.62.1.164:8080  
        real=10.62.1.166:8080 gate 1  
        real=10.62.1.165:8080 gate 1  
        scheduler=lc  
        persistent=90  
        protocol=tcp  
        checktype=connect  
        checkport=8080  
         
Le opzioni definite nel file ldirectord.conf sono le seguenti:  

- checktimeout: specifica il numero di secondi che ldirectord deve attendere per completare il check di un servizio. Se il controllo non dovesse essere completato entro il numero di secondi indicato, ldirectord rimuovera' il nodo dal bilanciamento.  
- checkinterval: indica l'intervallo di tempo in secondi tra i check eseguiti da ldirectord.  
- autoreaload: permette di abilitare l'opzione autoreaload. In pratica ldirectord calcola un checksum md5 del file di configurazione in modo da applicare automaticamente tramite ipvsadm eventuali modifiche in caso cambi il checksum del file in oggetto.  
- logfile: il file di log di ldirectord, dove verra' ad esempio registrato quando un nodo viene aggiunto o rimosso dal bilanciamento.  
- quiescent: un nodo viene considerato in stato quiescent nel caso non abbia riposto entro l'arco di tempo specificato dal parametro checktimeout.  
Se non si imposta questa opzione al valore no, se uno dei nodi dovesse crashare il cluster potrebbe apparire down per quei client che fossero bilanciati sul nodo in oggetto prima che esso diventasse irraggiungibile.  
- virtual: specifica l'indirizzo virtuale e la porta sulla quale LVS deve accettare le connessioni per poi inoltrarle ai nodi fisici, ovvero l'IP al quale i client devono puntare.  
- real: specifica l'indirizzo IP e la porta dei singoli nodi fisici, il metodo di forwarding e l'eventuale priorita' del nodo in oggetto. Questo parametro in particolare ha un sintesi simile alla seguente:  

    real=indirizzo_ip:porta gate|masq|ipip [weight]  

Ovviamente dovremo avere un'entry di questo tipo per ogni nodo fisico presente.  
Le parole chiavi gate,masq e ipip permettono di selezionare il metodo di forwarding, rispettivamente LVS-DR, LVS-NAT e LVS-TUN.  
Il peso del nodo, invece, viene utilizzato solo in presenza di algoritmi di scheduling pesati (ad esempio un weighted round robin) in modo da assegnare un peso maggiore a nodi con maggiore capacita' hardware.  
Nel caso specifico illustrato abbiamo due entry real che indicano la presenza di due nodi fisici 10.62.1.166 e 10.62.165, in ascolto sulla porta 8080, aventi il medesimo peso e gestiti tramite il metodo di forwarding direct routing (LVS-DR).  
Infine, si ricorda che il parametro real supporta anche ulteriori opzioni come ad esempio l'url di una pagina a cui fare una request e la risposta attesa, ma non essendo utilizzati nella mia configurazione non mi soffermo su di essi.  
- scheduler: specifica un algoritmo di bilanciamento da utilizzare, tra quelli elencati nell'infobox introduttivo. Nel mio caso ho adotatato un algoritmo di tipo Least Connection.  
- persistent: specifica il timeout per la persistenza delle connessioni. Per maggiori dettagli sulla persistenza si rimanda sempre all'infobox introduttivo.  
- protocol: il tipo di protocollo del servizio da bilanciare. Nel mio caso tcp, avendo i proxy in ascolto sulla porta tcp 8080.  
- checktype: questo parametro specifica la modalita' con la quale ldirectord dovra' verificare la disponibilita' del servizio sui nodi fisici, al fine di aggiungerli o rimuoverli dinamicamente al bilanciamento. Esistono diverse possibilita', per le quali si rimanda alla documentazione disponibile. Nel caso specifico e' stato scelta la modalita' connect, tramite la quale viene semplicemente effettuata una connessione alla porta utilizzata dal servizio per verificare se esso sia ancora in ascolto.  
- checkport: specifica la porta alla quale connettersi per verificare la disponibilita' del servizio sui nodi fisici.  
          
Una volta preparato l file di configurazionem per avviare il demone e' sufficiente dare il comando:  
  
ldirectord  /etc/ldirectord.conf  start  
  
Mentre per arrestarlo:  
  
ldirectord  /etc/ldirectord.conf  stop  
  
In alternativa e' possibile usare uno script di init in /etc/init.d/ ed avviare o stoppare il servizio con i comandi  /etc/init.d/ldirectord start e /etc/init.d/ldirectord stop:  
  
#!/bin/sh  

NAME=ldirectord  
DAEMON="/usr/sbin/$NAME"  
CONFIG="/etc/ldirectord.conf"  

test -x $DAEMON || exit 0  


case "$1" in  
        start)  
                $DAEMON $CONFIG start  
                ;;  
        stop)  
                $DAEMON $CONFIG stop  
                ;;  
        restart)  
                $DAEMON $CONFIG stop  
                $DAEMON $CONFIG start  
                ;;  
        status|reload|force-reload)  
                $DAEMON $CONFIG $1  
                ;;  
        *)  
                echo "Usage: /etc/init.d/$NAME" \  
                        "{start|stop|restart|status|reload|force-reload}" >&2  
        exit 1  
        ;;  
esac  
  
Infine, sui nodi fisici e' necessario configurare netfilter in modo da effettuare un destination nat delle richieste ricevute e destinate all'indirizzo IP virtuale assegnato al bilanciatore al fine di modificare l'indirizzo di destinazione (10.62.1.164) con quello del nodo (10.62.1.165 e 10.62.1.166).  
A tal fine e' necessario eseguire i seguenti comandi:  

- nodo 10.62.1.165:  
        
      echo 1 > /proc/sys/net/ipv4/ip_forward  
      iptables -t nat -I PREROUTING -i bond0 -d 10.62.1.164 -p tcp --dport 8080 -j DNAT --to-dest 10.62.1.165  
     
  
- nodo 10.62.1.166:  
        
      echo 1 > /proc/sys/net/ipv4/ip_forward  
      iptables -t nat -I PREROUTING -i bond0 -d 10.62.1.164 -p tcp --dport 8080 -j DNAT --to-dest 10.62.1.166  
     
  
In caso si desideri testare il funzionamento di LVS senza la necessita' di monitorare i servizi e possibile aggiungere e rimuovere nodi con il comando ipvsadm:  
  
ipvsadm -C  
ipvsadm -A -t 10.62.1.164:8080 -s lc  
ipvsadm -a -t 10.62.1.164:8080 -r 10.62.1.166 -g  
ipvsadm -a -t 10.62.1.164:8080 -r 10.62.1.165 -g  
  
Le opzioni utilizzate nelle linee di comando di ipvsadm per l'esempio riportato sono le seguenti:  

- -C, --clear: cancella la tabella del virtual server.  
- -A, --add-service: crea un servizio virtuale.  
- -a, --add-server: aggiunge un nodo ad un servizio virtuale.  
- -t, --tcp-service: specifica indirizzo ip e numero di porta tcp del servizio virtuale.
- -s, --scheduler: specifica l'algoritmo di bilanciamento  
- -r, --real-server: specifica l'indirizzo ip del nodo reale  
- -g, --gatewaying: indica il metodo di forwarding direct routing (LVS-DR)  

Per maggior dettagli sulle opzioni supportate da ipvsadm e' possibile fare riferimento alla relativa manpage.    

Il comando ipvsadm, inoltre, puo' essere utilizzato anche per visualizzare la configurazione del bilanciatore, indipendentemente dal fatto che venga gestito direttamente tramite ipvsadm o con ldirectord.  
In particolare lo stato del bilanciamento puo' essere visualizzato con il comando ipvsadm -L -n:  
  
IP Virtual Server version 1.2.1 (size=4096)  
Prot LocalAddress:Port Scheduler Flags  
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn  
TCP  10.62.1.164:8080 lc persistent 90  
  -> 10.62.1.165:8080             Route   1      52         1359        
  -> 10.62.1.166:8080            Route   1      32         1296      
  
Maggiori dettagli possono essere visualizzati con i seguenti comandi:  

    - ipvsadm -L -n --connection  
    L'opzione connnection permette di vedere le connessioni attualmente in essere sul bilanciatore, e lo stato delle stesse. In realta' l'output di questo comando non e' da giudicarsi particolarmente attendibile nella configurazione adottata. Transitando dal bilanciatore solo i pacchetti destinati ai nodi fisici e non le relative risposte molte connessioni appariranno in stato FIN_WAIT anche se in realta' potrebbero essere state correttamente terminate.  
Non vedendo il bilanciatore le risposte ai segmenti FIN dei client, per ognuno di essi mostrera' la connessione in stato FIN_WAIT, come nell'esempio seguente:  
          
        IPVS connection entries  
        pro expire state       source             virtual            destination  
        TCP 00:08  FIN_WAIT    10.65.49.39:3494   10.62.1.164:8080  10.62.1.165:8080  
        TCP 01:56  FIN_WAIT    10.80.49.38:1510   10.62.1.164:8080  10.62.1.166:8080  
        TCP 00:06  CLOSE       10.66.49.37:1704   10.62.1.164:8080  10.62.1.165:8080  
        TCP 00:02  NONE        10.222.198.135:0   10.62.1.164:8080  10.62.1.165:8080  
        TCP 14:59  ESTABLISHED 10.65.49.41:4465   10.62.1.164:8080  10.62.1.165:8080  
        TCP 00:06  CLOSE       10.144.49.41:4377  10.62.1.164:8080  10.62.1.165:8080  
        [...]  
        TCP 00:15  FIN_WAIT    10.144.49.38:4164  10.62.1.164:8080  10.62.1.165:8080  
        TCP 00:00  CLOSE       10.129.49.14:1301  10.62.1.164:8080  10.62.1.166:8080  
        TCP 00:08  CLOSE       10.66.49.37:1712   10.62.1.164:8080  10.62.1.165:8080  
        TCP 00:03  FIN_WAIT    10.145.49.35:1087  10.62.1.164:8080  10.62.1.166:8080  
        TCP 01:00  FIN_WAIT    10.153.14.24:2806  10.62.1.164:8080  10.62.1.166:8080  
        
  
    - ipvsadm -L -n --stats  
    L'opzione stats mostra il numero di connessioni, pacchett e bye scambiati delle statistiche generiche relative al numero di connessioni, pacchetti e byte ricevuti:  
    
        IP Virtual Server version 1.2.1 (size=4096)  
        Prot LocalAddress:Port               Conns   InPkts  OutPkts  InBytes OutBytes  
          -> RemoteAddress:Port  
        TCP  10.62.1.164:8080            54242260  457441K        0   73629M        0  
          -> 10.62.1.165:8080             28469454  239225K        0   38122M        0  
          -> 10.62.1.166:8080              398255  3335312        0  537157K        0  
        
  
    - ipvsadm -L -n --rate  
    L'opzione rate, infine, mostra la velocita' con la quale i pacchetti vengono inoltrati ai nodi fisici:  
                   
        IP Virtual Server version 1.2.1 (size=4096)  
        Prot LocalAddress:Port                 CPS    InPPS   OutPPS    InBPS   OutBPS  
          -> RemoteAddress:Port  
        TCP  10.62.1.164:8080                  39      320        0    45171        0  
          -> 10.62.1.165:8080                   19      132        0    21225        0  
          -> 10.62.1.166:8080                  21      188        0    23946        0  
        

Privacy Policy